import json
import os
import subprocess
import logging
import sys

from xToolkit import xfile

from checker.utils import request_get, write_as_excel, is_token_valid
from checker.utils_config import get_access_token_from_config
from checker.utils_str import form_name_for_org_repos_file, get_repo_name_from_repo_url

BASE_DIR = os.path.dirname(os.path.abspath(__file__))


def clone_single_repo_given_org_repo_name(organization, repo_name, clone_to_where,
                                          branch_or_tag='master', shallow=True):
    """
    根据组织名和仓库名，克隆仓库
    :param organization:组织名
    :param repo_name:仓库名
    :param clone_to_where:克隆地址
    :param branch_or_tag:分支选择
    :param shallow:浅克隆与否
    """
    repo_url = 'https://gitee.com/' + organization + '/' + repo_name
    print(f'正在检出{repo_url}仓库的{branch_or_tag}分支')
    clone_repo_given_url(repo_url, clone_to_where, branch_or_tag=branch_or_tag, shallow=shallow)


def clone_repo_given_url(repo_url, clone_to_where, branch_or_tag='master', shallow=True):
    """
    根据仓库url，克隆仓库
    :param repo_url: 仓库链接
    :param clone_to_where:克隆地址
    :param branch_or_tag:分支选择
    :param shallow:浅克隆与否
    """
    if not os.path.exists(clone_to_where):
        os.makedirs(clone_to_where, mode=0o777, exist_ok=False)
    repo_name = get_repo_name_from_repo_url(repo_url)
    repo_dir = os.path.join(clone_to_where, repo_name)
    if not os.path.exists(repo_dir):
        clone_repo(repo_url, clone_to_where, branch_or_tag=branch_or_tag, shallow=shallow)
    else:
        switch_and_update_repo(branch_or_tag, repo_dir, shallow=shallow)


def clone_repo(repo_url, working_dir, branch_or_tag='master', shallow=True):
    cmd = ['git', 'clone', repo_url, '-b', branch_or_tag]
    if shallow:
        cmd.append('--depth=1')
    run_command(cmd, cwd=working_dir, encoding='utf-8')


def switch_and_update_repo(branch_or_tag, working_dir, shallow=True):
    cmd = ['git', 'remote', 'set-branches', 'origin', branch_or_tag]
    run_command(cmd, cwd=working_dir, encoding='utf-8')

    cmd = ['git', 'fetch', 'origin', branch_or_tag]
    if shallow:
        cmd.append('--depth=1')
    run_command(cmd, cwd=working_dir, encoding='utf-8')

    cmd = ['git', 'checkout', branch_or_tag]
    run_command(cmd, cwd=working_dir, encoding='utf-8')

    cmd = ['git', 'reset', '--hard', 'origin/' + branch_or_tag]
    run_command(cmd, cwd=working_dir, encoding='utf-8')


def run_command(cmd, **kwargs):
    logging.info('cmd=' + str(cmd))
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, **kwargs)
    log_file = os.path.join(BASE_DIR, 'check.log')
    with open(log_file, 'a', encoding="utf-8") as f:
        for line in iter(process.stdout.readline, ''):
            # sys.stdout.write(line)
            # sys.stdout.flush()
            f.write(line)
            f.flush()
    process.wait()
    return process.returncode


def clone_repos_given_org_name(organization, clone_to_where, branch_or_tag='master', shallow=True):
    """
    根据组织名，克隆组织所有仓库
    :param organization:
    :param clone_to_where:克隆地址
    :param branch_or_tag:分支选择
    :param shallow:浅克隆与否
    """

    print(f'正在通过OpenAPI，获取{organization}组织的仓库名单')
    repo_url_list = get_org_repo_url_list(organization)
    print(f'正在获取或更新，{organization}组织的仓库')
    clone_repos_in_list(clone_to_where, repo_url_list, branch_or_tag, shallow)


def clone_repos_in_list(clone_to_where, repo_url_list, branch_or_tag='master', shallow=True):
    for i, repo_url in enumerate(repo_url_list):
        print(f'检出第{i + 1}个仓库, 总共{len(repo_url_list)}个仓库; 当前仓库{repo_url}')
        clone_repo_given_url(repo_url, clone_to_where, branch_or_tag, shallow)


def init_repo_info_excel(organization, renew_now=False):
    org_repos_stat_file = form_name_for_org_repos_file(organization)
    if renew_now or not os.path.exists(org_repos_stat_file):
        generate_repos_info_excel_for_org(organization, org_repos_stat_file)
    return org_repos_stat_file


def get_org_repo_url_list(organization, renew_now=False):
    org_repos_stat_file = init_repo_info_excel(organization, renew_now)
    repo_url_list = read_repos_list_from_stat_file(org_repos_stat_file)
    return repo_url_list


def read_repos_list_from_stat_file(org_repos_stat_file):
    repo_url_list = []
    repo_info_dict = xfile.read(org_repos_stat_file).excel_to_dict(max=float("inf"))
    for record in repo_info_dict:
        repo_url_list.append(record['仓库链接'])
    return repo_url_list


def generate_repos_info_excel_for_org(organization, output_file_name=None):
    if not output_file_name:
        output_file_name = organization + '_组织仓库清单.xlsx'
    repos_info_list = []
    repos_list = get_repos_list_for_org(organization)
    for repo in repos_list:
        process_repo_info_and_load_into_list(repo, repos_info_list)
    columns_order = ['仓库名称', '仓库链接', '仓库描述', '仓库状态', '创建时间']
    write_as_excel(output_file_name, repos_info_list, columns_order)


def process_repo_info_and_load_into_list(repo, repos_info_list):
    name = repo['name']
    link = 'https://gitee.com/' + repo['full_name']
    logging.debug(link)
    desc = repo['description']
    status = repo['status']
    created_at = repo['created_at']
    repos_info_list.append({"仓库名称": name, "仓库链接": link, "仓库描述": desc, "仓库状态": status, '创建时间': created_at})


def get_repos_list_for_org(organization):
    url_list = form_api_list_need_to_request(organization)
    repos_list = get_response_list_from_url(url_list)
    assert repos_list, f'目前识别输入的组织名为：{organization}请输入有效的组织名，例如：openharmony'
    return repos_list


def form_api_list_need_to_request(organization, max_pro_page=100):
    api_list = []
    access_token = get_access_token_from_config()
    assert is_token_valid(access_token), '请于config.toml, 配置有效的access_token'
    request_url = "https://gitee.com/api/v5/orgs/{}/repos?access_token={}&type=all&per_page=100&page={}"
    for page_num in range(1, max_pro_page):
        api_url = request_url.format(organization, access_token, page_num)
        api_list.append(api_url)
    return api_list


def get_response_list_from_url(url_list):
    response_list = []
    for request_url in url_list:
        json_response = get_json_response_from_url(request_url)
        if not json_response:
            break
        response_list.extend(json_response)
    return response_list


def get_json_response_from_url(request_url):
    response = request_get(request_url, timeout=100)
    json_obj_list = json.loads(response.text)
    if 'message' in json_obj_list:
        logging.error('访问url出错：' + request_url)
        logging.error('错误信息如下：' + json_obj_list['message'])
    if type(json_obj_list) == list and len(json_obj_list) > 0:
        return json_obj_list
    return []


if __name__ == '__main__':
    # 功能一：按仓库url名检出单个仓库
    test_url = 'https://gitee.com/openharmony/applications_app_samples.git'
    test_repo_dir = BASE_DIR + '/../output/openharmony_repos/'
    clone_repo_given_url(test_url, test_repo_dir)

    # 功能二：按组织名和仓库名检出单个仓库
    test_org_name = 'openharmony'
    test_repo_name = 'community'
    clone_single_repo_given_org_repo_name(test_org_name, test_repo_name, test_repo_dir)

    # 功能三：按组织名检出其所有仓库
    test_organization = 'openharmony-retired'
    test_repos_dir = BASE_DIR + '/../output/' + test_organization + '_repos/'
    clone_repos_given_org_name(test_organization, test_repos_dir)
